/* $RCSFile: LanguageCultureCollection.cs $
 * Apache license v2 2011 by Christian Surieux
 * $Source: ?/ADNCRM.Core/Helpers/LanguageCultureCollection.cs $
 * $log$
 * Revision 6 2010/08/06 19:56:28  christian.surieux
 *   Added Log to All cs files
 */

using System;
using System.Reflection;
using System.Diagnostics;
using System.CodeDom;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.ComponentModel.Design.Serialization;
using System.Globalization;
using System.Collections;

using AddonNice.Diagnostics;

namespace AddonNice.Helpers
{
	/// <summary>
	/// LanguageCultureCollection
	/// </summary>
	[TypeConverter(typeof(TypeConverterLanguageCultureCollection))]
	public class LanguageCultureCollection : CollectionBase, ICollection
	{
		private readonly char[] itemsSeparator = {';'};
		private readonly char[] keyValueSeparator = {'='};

		public LanguageCultureCollection()
		{
		}

		public LanguageCultureCollection(string LanguageCultureCollection)
		{
			LanguageCultureCollection mylist = (LanguageCultureCollection) LanguageCultureCollection;

			foreach(LanguageCultureItem l in mylist)
				Add(l);
		}

		public LanguageCultureItem this[Int32 i]
		{
			get{return (LanguageCultureItem) InnerList[i];}
//			set{InnerList[i] = value;}		
		}

		public void Add(LanguageCultureItem item)
		{
			InnerList.Add(item);
		}

		public void Insert(Int32 index, LanguageCultureItem item)
		{
			InnerList.Insert(index, item);
		}

		public virtual bool Contains(LanguageCultureItem item)
		{
			return InnerList.Contains(item);
		}

		public virtual int IndexOf(LanguageCultureItem item)
		{
			return InnerList.IndexOf(item);
		}

		public void Remove(LanguageCultureItem item)
		{
			InnerList.Remove(item);
		}

		// Provide the explicit interface member for ICollection.
		void ICollection.CopyTo(Array array, int arrayIndex)
		{
			InnerList.CopyTo(array, arrayIndex);
		}

		// Provide the strongly typed member for ICollection.
		public void CopyTo(LanguageCultureItem[] array, int index)
		{
			((ICollection)this).CopyTo(array, index);
		}

		public override string ToString()
		{
			System.Text.StringBuilder s = new System.Text.StringBuilder();
			foreach(LanguageCultureItem item in InnerList)
			{
				s.Append(item.UICulture.Name);
				s.Append(keyValueSeparator);
				s.Append(item.Culture.Name);
				s.Append(itemsSeparator);
			}
			return s.ToString();
		}

		/// <summary>
		/// Returns the best possible LanguageCultureItem 
		/// matching the provided culture
		/// </summary>
		/// <param name="culture"></param>
		/// <returns></returns>
		public LanguageCultureItem GetBestMatching(CultureInfo culture)
		{
			return GetBestMatching(new CultureInfo[] {culture});		
		}

		/// <summary>
		/// Returns the best possible LanguageCultureItem 
		/// matching cultures in provided list
		/// </summary>
		/// <param name="cultures"></param>
		/// <returns></returns>
		public LanguageCultureItem GetBestMatching(CultureInfo[] cultures)
		{
            if ( CoreTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]LanguageCultureCollection GetBestMatching cultures == null: {0}",cultures == null ),CoreTraceSwitch.Sw.Info);
			//If null return default
            if (cultures == null || cultures.Length == 0 || cultures[0] == null)
            {
                LanguageCultureItem it  =   (LanguageCultureItem)InnerList[0];
                if ( CoreTraceSwitch.Sw.TraceVerbose )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]LanguageCultureCollection GetBestMatching default: {0}",it.UICulture.Name ),CoreTraceSwitch.Sw.Info);
                return it;
            }

			//First pass, exact match
			foreach(CultureInfo culture in cultures)
			{
				for(Int32 i = 0; i < InnerList.Count; i++)
				{
					if (culture.Name == ((LanguageCultureItem) InnerList[i]).UICulture.Name)
                    {
                        LanguageCultureItem it  =   (LanguageCultureItem) InnerList[i];
                        if ( CoreTraceSwitch.Sw.TraceVerbose )
                            Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]LanguageCultureCollection GetBestMatching first pass: {0}",it.UICulture.Name ),CoreTraceSwitch.Sw.Info);
                        return it;
                    }
				}
			}
			//Second pass, we may accept a parent match
			foreach(CultureInfo culture in cultures)
			{
				for(Int32 i = 0; i < InnerList.Count; i++)
				{
					if (culture.Parent.Name == ((LanguageCultureItem) InnerList[i]).UICulture.Name)
                    {
                        LanguageCultureItem it  =   (LanguageCultureItem) InnerList[i];
                        if ( CoreTraceSwitch.Sw.TraceVerbose )
                            Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]LanguageCultureCollection GetBestMatching second pass: {0}",it.UICulture.Name ),CoreTraceSwitch.Sw.Info);
                        return it;
                    }
				}
			}
			//CS May 2004 third pass, we may accept a parent match
			foreach(CultureInfo culture in cultures)
			{
				for(Int32 i = 0; i < InnerList.Count; i++)
				{
					if (culture.Name == ((LanguageCultureItem) InnerList[i]).UICulture.Parent.Name)
                    {
                        LanguageCultureItem it  =   (LanguageCultureItem) InnerList[i];
                        if ( CoreTraceSwitch.Sw.TraceVerbose )
                            Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]LanguageCultureCollection GetBestMatching parent match: {0}",it.UICulture.Name ),CoreTraceSwitch.Sw.Info);
                        return it;
                    }
				}
			}
            if ( CoreTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine("[V]LanguageCultureCollection GetBestMatching no match",CoreTraceSwitch.Sw.Info);
			return null; //no applicable match
		}

		/// <summary>
		/// Returns a CultureInfo list matching language property
		/// </summary>
		/// <param name="addInvariantCulture">If true adds a row containing invariant culture</param>
		/// <returns></returns>
		public CultureInfo[] ToUICultureArray(bool addInvariantCulture)
		{
			ArrayList cultures = new ArrayList();
			if (addInvariantCulture)
				cultures.Add(CultureInfo.InvariantCulture);

			for(Int32 i = 0; i < InnerList.Count; i++)
			{
				cultures.Add(((LanguageCultureItem) InnerList[i]).UICulture);
			}
			return (CultureInfo[]) cultures.ToArray(typeof(CultureInfo));
		}

		/// <summary>
		/// Returns a CultureInfo list matching language property
		/// </summary>
		/// <returns></returns>
		public CultureInfo[] ToUICultureArray()
		{
			return ToUICultureArray(false);
		}

		/// <summary>
		/// Explicitly converts String to LanguageCultureCollection value
		/// </summary>
		/// <returns></returns>
		static public explicit operator LanguageCultureCollection(string languageList)
		{
			return (LanguageCultureCollection) TypeDescriptor.GetConverter(typeof(LanguageCultureCollection)).ConvertTo(languageList, typeof(LanguageCultureCollection));
		}

		/// <summary>
		/// Explicitly converts LanguageCultureCollection to String value
		/// </summary>
		/// <returns></returns>
		static public explicit operator String(LanguageCultureCollection langList)
		{
			return (string) TypeDescriptor.GetConverter(typeof(LanguageCultureCollection)).ConvertTo(langList, typeof(string));
		}
	}
}
